/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.mlbs.session;

import com.mlbs.entity.Application;
import com.mlbs.entity.Device;
import com.mlbs.entity.Devicelocation;
import com.mlbs.entity.Preferences;
import com.mlbs.entity.Usersession;
import com.mlbs.entity.Usertable;
import com.mlbs.helper.Address;
import com.mlbs.helper.GeoCoordinate;
import com.mlbs.helper.Location;
import java.util.Collection;
import java.util.Date;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 * This class provides the Location services for the middleware. These include 
 * getting address in terms of physical address, coordinates and also reverse geo coding i.e. 
 * interconversion between physical address and coordinates.
 * @author hubharan
 */
@PersistenceContext(name="mlbs-ejbPU", unitName="mlbs-ejbPU")
@Stateless
public class LocationServicesSBBean implements LocationServicesSBLocal {
    @PersistenceContext(unitName="mlbs-ejbPU")
    private EntityManager em;
    
    public EntityManager getEntityManager() {
        return em;
    }
    
    /**
     * Get the location of the device in terms of address bsed on the 
     * preferences set for that particular application.
     * @param appId Application Identification
     * @param deviceId Device Identification
     * @return Address object which contains street, city, state, etc.
     */
    public Address getAddress(int appId, String deviceId) {
        Application app = (Application)getEntityManager().
                createNamedQuery("Application.findByAppId").
                setParameter("appId", appId).getSingleResult();
        
        Device dev = (Device)getEntityManager().
                createNamedQuery("Device.findByDeviceid").
                setParameter("deviceid", deviceId).getSingleResult();
        Usertable user = dev.getUserid();
        //Get user pref for the app, if privicy allows then proceed, else return null
        Collection<Preferences> pref  = user.getPreferencesCollection();
        //iterate over pref and check for app id
        
        Devicelocation loc = dev.getDevicelocation();
        Address addr = new Address();
        addr.setCity(loc.getCity());
        addr.setState(loc.getState());
        addr.setStreetAddress(loc.getStreet());
        return addr;
    }

    /**
     * Get the location of the device in terms of Latitude, Longitude based 
     * on the preferences for that application. 
     * @param appId Application Identification
     * @param deviceId Device Identification
     * @return GeoCoordinate object capable of holding latitude and longitude
     */
    public GeoCoordinate getLocationCoordinates(int appId, String deviceId) {
        Application app = (Application)getEntityManager().
                createNamedQuery("Application.findByAppId").
                setParameter("appId", appId).getSingleResult();
        
        Device dev = (Device)getEntityManager().
                createNamedQuery("Device.findByDeviceid").
                setParameter("deviceid", deviceId).getSingleResult();
        Usertable user = dev.getUserid();
        //Get user pref for the app, if privicy allows then proceed, else return null
        Collection<Preferences> pref  = user.getPreferencesCollection();
        //iterate over pref and check for app id
        
        Devicelocation loc = dev.getDevicelocation();
        GeoCoordinate cord = new GeoCoordinate();
        cord.setLat(loc.getLat().longValue());
        cord.setLongitude(loc.getLongitude().longValue());
        return cord;
    }

    /**
     * Get the Latitude, longitude for the particular address passwed.
     * @param address
     * @return GeoCoordinate object capable of holding latitude and longitude
     */
    public GeoCoordinate getRevGeoCoordinates(Address address) {
        //Make a call to yahoo or our DB and return Geo cords for address
        GeoCoordinate cord = new GeoCoordinate();
        cord.setLat(0);
        cord.setLongitude(0);
        return cord;
    }
    /**
     * Map the passed latitude and longitude to a physical address
     * @param coordinates contains latitude and longitude that are to be mapped
     * @return Address object which contains street, city, state, etc.
     */
    public Address getRevGeoCoordinates(GeoCoordinate coordinates) {
        //Make a call to yahoo or our DB and return Geo cords for address
        Address addr = new Address();
        addr.setCity("");
        addr.setState("");
        addr.setStreetAddress("");
        return addr;
    }

    /**
     * Used by the app sitting on the client side, at a fixed interval, to 
     * update the server of current location 
     * @param deviceId Device Identification
     * @param session Session Object returned by the authentication method
     * @param location Location object passed by the client app.
     * @return
     */
    public boolean updateDeviceLocation(String deviceId, String session, Location location) {
        Usersession sess = (Usersession)getEntityManager().
                createNamedQuery("Usersession.findBySession").
                setParameter("session", session).
                getSingleResult();
        Usertable user = (Usertable)getEntityManager().
                createNamedQuery("Usertable.findByUserId").
                setParameter("userId", sess.getId()).
                getSingleResult();
        //Get the device out of device location
        Collection<Device> dev = user.getDeviceCollection();
        Devicelocation loc = new Devicelocation(deviceId, new Date());
        ((Device)(dev.toArray()[0])).setDevicelocation(loc);
        em.persist(loc);
        return true;
    }
    
    
    // Add business logic below. (Right-click in editor and choose
    // "EJB Methods > Add Business Method" or "Web Service > Add Operation")

}
